home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / programm.ing / progem.lzh / wind17.prf < prev    next >
Encoding:
Text File  |  1987-06-23  |  22.5 KB  |  474 lines

  1. .!****************************************************************************
  2. .! 
  3. .! ANTIC PUBLISHING INC., COPYRIGHT 1985.  REPRINTED BY PERMISSION.
  4. .!
  5. .! ** Professional GEM ** by Tim Oren
  6. .!
  7. .! Proff File by ST enthusiasts at
  8. .! Case Western Reserve University
  9. .! Cleveland, Ohio
  10. .! uucp : decvax!cwruecmp!bammi
  11. .! csnet: bammi@case
  12. .! arpa : bammi%case@csnet-relay
  13. .! compuserve: 71515,155
  14. .!
  15. .!****************************************************************************
  16. .!
  17. .!
  18. .!****************************************************************************
  19. .!
  20. .!            Begin Part XVII
  21. .!
  22. .!****************************************************************************
  23. .!
  24. .PART XVII PC/ST Resource Converter
  25. .PP
  26. This the seventeenth installment of ST PRO GEM, the
  27. first to feature a complete GEM application.  The program
  28. converts resource files between the ST (68000) and IBM PC
  29. (Intel) formats used by the respective versions of GEM and
  30. the Resource Construction Set.
  31. .PP
  32. The Resource Converter will, for the most part, be of
  33. direct use only if you are doing cross-development of GEM
  34. software on these two systems.  In this case, you will want
  35. to read this entire article, starting with the "What It Does"
  36. heading.  You may also be interested in an article on PC/ST
  37. conversion written by Mark Skapinker of Batteries Included,
  38. which appears in the Fall issue of START magazine (available
  39. September 1986).
  40. .PP
  41. If you are not doing cross machine development, you can
  42. still get something out of this column.  Reading the program
  43. code and following the discussion, you will find practical
  44. examples of using GEM dialogs and following the internal
  45. structure of a resource file.  Finally, there is a good deal
  46. of standard code for GEM initialization, AES utility
  47. functions, and GEMDOS file handling which you can extract for
  48. your own uses.  If you fall in this category, skip the first
  49. parts of the column, and resume reading at the "How it Works"
  50. heading.
  51. .PP
  52.      The download for this column is a set of source and
  53. binary files located on DL3 of the ATARI16 SIG, PCS-58.  The
  54. files and their contents are:
  55.  
  56.      RCMAIN.C   -  Download and rename to RSCVMAIN.C
  57.                     This is the C source for main routine
  58.      RCFILE.C   -  Download and rename to  RSCVFILE.C
  59.                     This is the C source of GEMDOS utilities
  60.      RCLIB.C    -  Download and rename to RSCVLIB.C
  61.                     C source of AES utility functions
  62.      RSCONV.PRG -  Linked binary of converter
  63.      RSCONV.RSC -  Binary resource image (ST format)
  64.      RSCONV.DFN -  Symbol file for resource (ST format for
  65.                     RCS 2.0)
  66.      RSCONV.H   -  Object/tree name file for resource
  67.      RLINK.SH   -  Download and rename to RSCVLINK.SH
  68.                     C-shell script for linking RSCONV
  69.      SYLINK.SH  -  Download and rename to SYMLINK.SH
  70.                     Another script, used by RSCVLINK.SH
  71. .PP
  72. The final two files will be of use only if you are using Dave
  73. Beckemeyer's Micro C-Shell environment.  If not, you can
  74. simply translate them to .BAT and/or .INP form for use with
  75. the Atari batch program and linker.
  76. .SH WHAT IT DOES
  77. A converter program is necessary because of the
  78. differing order of storage on the 68000 and Intel chips:  the
  79. order of significance of bytes within words is reversed, as
  80. well as the order of words within long (32-bit) quantities.
  81. Attempting to load an unconverted resource on a GEM system
  82. with the other architecture will result in a crash, because
  83. all of the pointer and integer fields will be incorrect.
  84. .PP
  85. In addition, the format of symbol definition (DEF) files
  86. differs between the PC and ST implementations of the RCS in
  87. its first version.  In the latest version from DRI, the
  88. formats do correspond, and the files now carry an extent name
  89. of DFN.  However, the byte swapping problem must be corrected
  90. in either format for the symbols to be correctly loaded.
  91.      As final touch, the converter also checks to be sure
  92. that a resource being loaded from the PC has its bit images
  93. synchronized to an even byte boundary.  If this is not
  94. corrected, the ST will suffer a bus error when attempted to
  95. address the images with a word type operation, which will
  96. certainly happen in either the RCS or the application itself
  97. on the target system.
  98. .SH OPERATION
  99. When the Resource Converter loads, it presents an
  100. initial dialog box.  (The converter does not use the menu
  101. bar.) The dialog has action buttons at the bottom labelled
  102. "Help", "Convert" and "Quit".  Clicking the Help button will
  103. obtain a screen which summarizes these operating
  104. instructions.  The Quit button terminates the program.
  105. Clicking Convert initiates the program's action, according to
  106. the options you have set in the rest of the dialog.
  107. .PP
  108. The top two buttons in the dialog establish the
  109. direction of the conversion.  If you have built a resource on
  110. the PC and want to move it to the ST, click Intel->68000.  If
  111. you are moving the file from the ST to the PC, click
  112. 68000->Intel.
  113. .PP
  114. The next two lines in the dialog establish the file
  115. extent names which will be used for the conversion.  The
  116. input extent names are always on the left, no matter which
  117. conversion mode you selected above.  By default, they are RSC
  118. and DEF.  The output extents, on the right, are RS2 and DF2
  119. by default.  The RSC/RS2 file extents are used for the
  120. resource, and DEF/DF2 extents are for the symbol file.  Be
  121. careful that the input files you use are actually of the type
  122. (Intel or 68000) which you specified.  If you get it
  123. backwards, the ST will most likely crash, though the input
  124. files will not be harmed.
  125. .PP
  126. The three buttons below the file extents determine the
  127. format of the input and output symbol files.  If you click on
  128. DEF, the Resource Converter will assume that the input and
  129. output symbol files are in the old (that is, version 1.1)
  130. format used by the RCS.  If you click on DFN, the program
  131. expects the new (version 2.0) symbol format.  If the input
  132. symbol file extent is still set to "DEF", clicking this
  133. button will also change it appropriately.  (Note that the DEF
  134. and DFN formats are in fact IDENTICAL on the PC ONLY.  To
  135. "change formats" ON THE PC, you need only change the file's
  136. extent name, for example, rename FOOBAZ.DEF to FOOBAZ.DFN.
  137. On the ST, there is a real difference,and you must use the
  138. DRI DEF2DFN.PRG utility to go from old to new.)
  139. .PP
  140. The last button option is (OFF).  Clicking this button
  141. disables the symbol file conversion.  You may use this option
  142. to keep better control over versions of your resource.  By
  143. establishing the main version on either the PC or ST, and
  144. converting only the resource file, not the symbols, you can
  145. ensure that no one will use the RCS on the destination
  146. machine to create a version which is different from the
  147. source.
  148. .PP
  149. When the Convert button is clicked to begin execution,
  150. the standard Item Selector is displayed.  Use it to find and
  151. pick the input resource file which you want to convert.  The
  152. Converter will use its main filename, substituting the
  153. various extents, to find the input definition file, and
  154. produce the output file names.  If the definition file cannot
  155. be found in the same directory under the generated name, you
  156. will be presented with an alert, asking you to abort the
  157. conversion, continue without the symbol file, or specify a
  158. new name and/or directory for the file.  If the output names
  159. coincide with existing files, they will be overwritten.
  160. .PP
  161. While the conversion operation is occurring, a progress
  162. indicator box will be displayed on the screen, with text
  163. messages indicating the current phase of the operation.  When
  164. the conversion is complete, you are returned to the initial
  165. dialog, where you may quit or perform another conversion.
  166. .PP
  167. One last note on conversion, with a caution:  it is
  168. possible to move files between Intel and 68000 even if you
  169. have two different versions of the Resource Construction Set,
  170. for instance, Version 2.0 on the PC and Version 1.1 on the
  171. ST.  In this situation, you can take advantage of the
  172. identity between symbol file formats on the PC.  Make a copy
  173. of the PC symbol file into another file with the DEF extent,
  174. and run the converter.  The output should load on the ST
  175. version correctly.  However, if you move symbols between
  176. different RCS versions, you MUST NOT use the "free strings"
  177. and "free images" features of version 2 and then move the
  178. symbols to version 1.  Doing so may result in spurious
  179. assignment of the "free" symbols to trees and objects, and
  180. you will (of course) not be able to edit the free images
  181. and/or strings in the resource.
  182. .SH HOW IT WORKS
  183. For the ST-only developers now rejoining the discussion,
  184. I will now take a look at the standard GEM initialization
  185. code and the special dialog handling techniques which I have
  186. used in the Converter.  Then we'll look at the guts of the
  187. code, which threads through the resource to do the actual
  188. conversion.  For those interested in the supporting code
  189. libraries, the GEMDOS interface utilities in RSCVFILE.C were
  190. described in column number 15.  The progress indicator
  191. functions of RCSLIB.C were detailed in column 16, and
  192. map_tree() and standard dialog handling techniques were
  193. discussed in columns three through five.
  194. .PP
  195. There are a number of useful facts in rscv_init(), the
  196. initialization code.  First, notice that the result of
  197. appl_init is NOT assigned directly to gl_apid.  Due to a bug
  198. in the appl_init binding the application ID is not returned
  199. as the function value.  Instead it is returned to the global
  200. variable gl_apid.  This bug wouldn't cause direct problems in
  201. the resource converter, but it will in any program which uses
  202. the ID when sending messages to its own pipe.
  203. .PP
  204. Next, an alert string to be displayed if the resource is
  205. not found has been explicitly included, to avoid a "Catch-22"
  206. situation.  You can easily create such a string by building
  207. the alert in the RCS, using the C output option, and
  208. extracting the string from the resulting file.
  209. .PP
  210. Rscv_init() then sets up its VDI handle, by getting the
  211. physical workstation handle from graf_handle, and passing it
  212. to v_opnvwk (open virtual workstation), which returns the
  213. virtual workstation handle for use in VDI calls.  V_opnvwk
  214. also returns the dimensions of the screen, which are copied
  215. to GRECT scrn_area, and the number of color planes, which is
  216. used to set up an MFDB for the screen:  scrn_mfdb.
  217. .PP
  218. The wind_get call for the working area of the DESK
  219. window (number zero) results in the usable GRECT of the
  220. screen.  This is different from scrn_area, because the menu
  221. bar's rectangle is reserved for the system.
  222. .PP
  223. You may want to take particular notice of the vst_height
  224. call, which reloads the character dimension variables.  The
  225. values returned earlier by graf_handle are ALWAYS for the
  226. monochrome (high resolution) system font, and they are not
  227. appropriate for the low and medium resolution modes of the
  228. ST.  Performing the vst_height call AFTER opening the virtual
  229. workstation will get the correct dimensions.
  230. .PP
  231. Some of the environment variables which are set up by
  232. rscv_init(), are not actually used in the resource converter.
  233. I have included them because they are part of my "generic"
  234. initialization procedures.
  235. .PP
  236. Finally, rscv_init() uses Malloc to reserve most of
  237. memory as a working buffer for the resource conversion.
  238. Notice that 4K are left free.  You must leave at least 2K,
  239. and preferably a safety factor, or the AES will be unable to
  240. allocate memory for the file selector dialog, and your
  241. application will hang when calling fsel_input.  By the way,
  242. an open virtual workstation uses about 8K, so you should do
  243. your Mallocs after the workstation call.
  244. .PP
  245. We now turn our attention to do_mode(), which handles
  246. the main dialog of the converter.  After getting the root
  247. address of the dialog tree, the states of global variables
  248. conv_def and new_dfn are used to set up the radio button
  249. array for symbol file conversion.  Native_in is used to set
  250. up the conversion type radio buttons.  The last
  251. initialization step is to use the set_text() utility to link
  252. the file extent strings into the appropriate editable
  253. objects.  Notice that this version of set_text() allows the
  254. string length to be explicitly supplied.  For an editable
  255. text field object (G_FTEXT or G_FBOXTEXT), the length must be
  256. one greater than the number of blanks in the editing
  257. template.
  258. .PP
  259. Since there are TOUCHEXIT objects in the dialog, we
  260. cannot use the standard hndl_dial() routine.  Instead, the
  261. form setup and draw calls are coded inline.  The actual
  262. form_do call is placed inside a loop.  If the object returned
  263. is not one of the TOUCHEXIT objects, the loop is terminated.
  264. .PP
  265. The two objects DEFYES and DFNYES, which select the old
  266. and new symbol file formats, respectively, have been made
  267. TOUCHEXIT.  If either is clicked, the radio button processing
  268. is done by the AES, but then control is returned from
  269. form_do.  Do_mode() then tests the current input symbol file
  270. extent.  If it is "DEF" and we are switching from old to new
  271. mode, the extent is changed to "DFN".  When switching from
  272. new to old mode, the reverse check is made.  In either case,
  273. the disp_obj() utility is used to force an immediate redraw
  274. before returning to form_do for further user input.
  275. .PP
  276. When the loop terminates, do_mode() cleans up the screen
  277. with form_dial, and uses the selected() utility to retrieve
  278. the status of the radio button arrays and update the global
  279. variables.  Finally, map_tree() is used to apply the
  280. deselection utility to all objects in the tree, leaving it
  281. clean for the next invocation of do_mode().
  282. .SH THE BELLY OF THE BEAST
  283. The routine dconv() contains the code for actually
  284. converting the resource.  About half of do_conv() is devoted
  285. to accessing disk files, and correctly handling error
  286. conditions which might arise.  The error recovery could
  287. perhaps be handled more concisely with artifices like
  288. "setjmp", but I have left it in-line for the sake of clarity.
  289. .PP
  290. Do_conv() also uses a collection of routines whose names
  291. begin with "swap_" Swap_bytes() and swap_words() are the
  292. workhorse routines.  They simply run through a given area of
  293. memory, reversing every pair of bytes or words, respectively.
  294. (Remember that the word swapper will only work on even byte
  295. boundaries, or a bus fault will occur.) The other swap
  296. routines do the fix up for one type of resource structure
  297. each.  I'll take apart a couple in detail, so that you can
  298. see the similarities in the others.
  299. .PP
  300. Now let's follow the do_conv() code.  The first item of
  301. business is to use the get_file() utility, followed by
  302. open_file(), to find and open the input resource file.
  303. Again, you can see column 15 for a a discussion of these
  304. routines, which will handle DOS errors if they occur.
  305. .PP
  306. The Boolean conv_def is true if we need to open a
  307. symbols file.  If everything goes right, just substituting a
  308. new extent name (from variable old_def), and doing the file
  309. open will get the file.  If things foul up, do_conv() has to
  310. recover gracefully.  So, it puts up the three button alert
  311. NODEF.  The third button is an abort option;  if it's picked
  312. we punt, closing the one open file and returning to the main
  313. dialog.  Button one allows a continuation without the
  314. definition file (conv_def is forced FALSE so the user won't
  315. make the same mistake twice).  Button two says try again, so
  316. get_file() is called to pick another file, and the whole
  317. process repeats.
  318. .PP
  319. Once the input file(s) are open, the operation will run
  320. to completion, assuming no disk errors.  The mouse form is
  321. switched to an hour glass, and a progress indicator box is
  322. initialized on the screen.
  323. .PP
  324. The first action is to bring in the resource header
  325. only.  If the resource is not native, that is, is not in
  326. 68000 format, its bytes must be swapped before using any of
  327. the counts and offsets.  Note:  if you've never dissected a
  328. resource before, this would be a good time take a look at the
  329. header format given in "gemdefs.h" in the Developer's Kit,
  330. and the resource structure definitions in "obdefs.h".
  331. .PP
  332. After the swap, if necessary, the resource size field
  333. can be used.  Before reading the rest of the resource, the
  334. size must be compared against the size of the buffer
  335. allocated during initialization.  If there isn't enough room,
  336. the NOMEM alert is displayed and control returns to the main
  337. dialog.  (Since the biggest resource is 64K, and the
  338. Converter is rather small, this shouldn't ever happen.  But,
  339. some people load up lots of desk accessories, so best to be
  340. prepared.)
  341. .PP
  342. After completing the resource input, an (admittedly
  343. kludgy) patch is made for the odd-byte-images problem.  If
  344. the image offset pointer is odd, there will be problems on
  345. the ST.  The fix made here relies on two facts.  First, all
  346. images are an even number of bytes in size.  Second, the old
  347. version of RCS DOES do an even byte synchronization AFTER
  348. writing the images.  Therefore, if the images start on an odd
  349. byte, they will end on an even byte, and have one unused
  350. odd-addressed byte immediately following.  The fixup strategy
  351. is to move all of the images up one byte, patch the offset in
  352. the header accordingly, and leave the img_odd flag set so
  353. that the bit image swap routine will also increment pointers
  354. in the BITBLK and ICONBLKs which use the images.
  355. .PP
  356. If the resource being converted is native, we can do the
  357. image fixup immediately.  If not, all of the other swaps have
  358. to take first, because the long pointers in the BITBLKs and
  359. ICONBLKs are in the wrong order.  (We don't have to swap
  360. string data;  it's always stored in ascending order.)
  361. .PP
  362. Do_conv() calls subroutines to swap the tree index,
  363. objects, TEDINFOs, ICONBLKs, BITBLKs, and free string and
  364. images, in that order.  We'll look at their actual code
  365. later.  When this is finished, one of two cleanup actions is
  366. needed.  If the resource WAS native, everything is now
  367. swapped except the header, which is finally reversed.  If it
  368. used to be foreign (Intel), the pointers are now in proper
  369. 68000 order, so swap_images() can be called successfully.
  370. .PP
  371. Now it's time to write the converted resource, taking
  372. care that no error results.  If no symbol file conversion is
  373. needed, do_conv() is done.  The files are closed, the
  374. progress indicator completed, and control returns to
  375. rscv_run, which will set the cursor back to the arrow.
  376. Otherwise, it's time to handle the symbols file.
  377. .PP
  378. The first two bytes in the definition file are always
  379. the symbol count.  They are read into nsym, and a scratch
  380. copy is made in reply, and swapped.  Just which version is
  381. written to the output file depends on whether it is a DFN or
  382. DEF file.  The new (DFN) format keeps a similar word order on
  383. both the ST and PC.  For these files, the following code
  384. amounts to a verbatim copy.
  385. .PP
  386. Nsym is now used as the control variable of a loop which
  387. reads, converts, and writes one symbol entry on each
  388. iteration.  In the old (DEF) file format, there was an extra
  389. word in the value field of each symbol's entry on the ST.
  390. Going from PC to ST, two padding zero bytes are added.  Going
  391. the other way, they are read and discarded.  For the old
  392. format, both the significant word of this field, as well as
  393. the following word field (the type) are swapped.  The ten
  394. symbol bytes are passed through verbatim in both new and old
  395. format.
  396. .PP
  397. After swapping (old format) or simply copying (new
  398. format) of the symbol file is completed, file and progress
  399. box cleanup is done, and control returns.
  400. .SH THE OL' SWITCHEROO
  401.      As promised, let's now go and look at a sampling of
  402. the structure swap routines:  one of the simplest (tree
  403. index), one of medium complexity (objects), and the
  404. worst of the bunch (bit images).
  405. .PP
  406. Swap_trees() is responsible for fixing the tree index.
  407. Its location is found by adding an offset from the header
  408. (rsh_trindex) to the base address of the resource, stored in
  409. head.  (Notice that head was defined as a byte pointer when
  410. the buffer was allocated, so I need to type coerce it to a
  411. resource header pointer before making structure references.)
  412. The number of trees is stored in the rsh_ntree header field.
  413. Each index entry is a long pointer of 32-bits, so the total
  414. size of the index may be found by multiplication.  Finally,
  415. the swapping is done, first bytes within words, then words
  416. within the long pointers.  (The order doesn't matter - work
  417. it out!)
  418. .PP
  419. Swap_objs() takes care of swapping fields inside of
  420. object structures.  It begins similarly to swap_trees(),
  421. computing the base address of the objects from rsh_object,
  422. and taking the count from rsh_nobs.  Since all of the objects
  423. are contiguous in a resource produced by RCS, and all fields
  424. of an object are words or longs, a byte swap is performed on
  425. the entire block at once.  Now there are a couple of tricks.
  426. Notice that "where" in this routine is typed as an object
  427. pointer.  As the number of objects is counted down in the
  428. loop, "where" is incremented.  Because of its type, its
  429. actual pointer value will increase by sizeof(OBJECT) at each
  430. iteration.  Inside the loop, only one long field, the
  431. ob_spec, needs to be word swapped.  When the loop completes,
  432. all object structures are fixed.
  433. .PP
  434. Swap_fstr() and swap_fimg() use code similar to
  435. swap_trees().  The other resource structures, TEDINFOs,
  436. ICONBLKs, and BITBLKs, are transformed by code similar to
  437. swap_objs().  There is one subtlety here.  These structures
  438. would normally be reaching by following an object's ob_spec
  439. pointer.  To finesse a "swap now or later" ordering problem
  440. with the objects, I have instead used the resource header to
  441. find the structure arrays.  You SHOULD NOT use this technique
  442. at run time, for two reasons.  First, if you do any object
  443. patching on the fly, the correspondence between objects and
  444. reference strucutres will be destroyed.  Second, there is no
  445. way to name a non-object structure with the RCS, and
  446. therefore no way to reliably retrieve it with rsrc_gaddr at
  447. execution time.
  448. .PP
  449. Last but not least, swap_images() not only takes care of
  450. switching bit image words, but also fixes image pointers as
  451. necessary if an odd byte problem has been detected.  For
  452. these reasons, swap_images DOES follow pointers from the
  453. ICONBLKs and BITBLKs.  The loop structure of the two sections
  454. of code will be familiar from swap_ibs() and swap_bbs().
  455. Size fields within the structure are used to determine the
  456. length of each image.  If the img_odd flag has been set, the
  457. data pointer must be incremented BEFORE doing the swap, since
  458. the underlying data has already been moved.
  459. .SH PHEW!
  460. This column was deliberately long, in hopes that even
  461. those with no immediate use for this program will gain from
  462. the discussion.  Do to space limits, the feedback is
  463. postponed to episode number 18, which will be another helping
  464. of "interface potpourri".  Ingredients will include the popup
  465. menu code (finally), along with generic code for scrolling
  466. windows, and building your own scroll bars within dialogs.
  467. .!
  468. .!
  469. .!*****************************************************************************
  470. .!*                                          *
  471. .!*                End Part 17                      *
  472. .!*                                          *
  473. .!*****************************************************************************
  474.